<HTML>
<HEAD>
<TITLE>Another Look at the Date Format String</TITLE>
<LINK REL=StyleSheet HREF="../rw.css" TYPE="text/css" TITLE="Rogue Wave Standard Stylesheet"></HEAD>
<BODY BGCOLOR=#FFFFFF>
<A HREF="36-2.html"><IMG SRC="images/bprev.gif" WIDTH=20 HEIGHT=21 ALT="Previous file" BORDER=O></A><A HREF="noframes.html"><IMG SRC="images/btop.gif" WIDTH=56 HEIGHT=21 ALT="Top of Document" BORDER=O></A><A HREF="booktoc.html"><IMG SRC="images/btoc.gif" WIDTH=56 HEIGHT=21 ALT="Contents" BORDER=O></A><A HREF="tindex.html"><IMG SRC="images/bindex.gif" WIDTH=56 HEIGHT=21 ALT="Index page" BORDER=O></A><A HREF="36-4.html"><IMG SRC="images/bnext.gif" WIDTH=25 HEIGHT=21 ALT="Next file" BORDER=O></A><DIV CLASS="DOCUMENTNAME"><B>Rogue Wave C++ Standard Library User's Guide</B></DIV>
<H2>36.3 Another Look at the Date Format String</H2>
<A NAME="idx891"><!></A>
<P>We would like to store the date format string in the iostream storage through <SAMP>std::ios_base::iword()</SAMP> and <SAMP>std::ios_base::pword()</SAMP>. In this way, the input and output operations for <SAMP>date</SAMP> objects can access the format string for parsing and formatting. Format parameters are often set with manipulators (see <A HREF="28-3.html#2832">Section&nbsp;28.3.2</A>), so we should add a manipulator that sets the date format string. It could be used like this:</P>

<UL><PRE>
date today;
std::ofstream ostr;
// ...
ostr &lt;&lt; setfmt("%D") &lt;&lt; today;
</PRE></UL>
<A NAME="idx892"><!></A>
<P>Here is a suggested implementation for such a manipulator (note that the name of the base class is implementation-defined):</P>

<UL><PRE>
class setfmt : public <I>smanip</I>&lt;const char*&gt;
{
 public:
  setfmt(const char* fmt)
  : <I>smanip</I>&lt;const char*&gt;(setfmt_,fmt) {}
 private:
  static const int datfmtIdx;                                 //1

  static std::ios_base&amp; setfmt_(std::ios_base&amp; str,
                                const char* fmt)
  {
    str.pword(datfmtIdx) = const_cast&lt;char*&gt; (fmt);           //2
    return str;
  }

  template&lt;class charT, class Traits&gt;
  friend std::basic_ostream&lt;charT, Traits&gt;&amp;                   //3
  operator&lt;&lt;(basic_ostream&lt;charT, Traits&gt;&amp; os,
             const date&amp; dat);
};

const int setfmt::datfmtIdx = std::ios_base::xalloc();        //4
</PRE></UL>
<A NAME="idx893"><!></A>
<P>The technique applied to implement the manipulator is described in detail in Example 2 of <A HREF="33-3.html">Section&nbsp;33.3</A>, so we won't repeat it here. But regarding this manipulator and the private use of iostream storage, there are other interesting details:</P>
<TABLE CELLPADDING="3">

<TR VALIGN="top"><TD><SAMP>//1</SAMP></TD><TD>The manipulator class owns the index of the element in the iostream storage where we want to store the format string. It is initialized in <SAMP>//4</SAMP> by a call to <SAMP>xalloc()</SAMP>.
<TR VALIGN="top"><TD><SAMP>//2</SAMP></TD><TD>The manipulator accesses the array <SAMP>pword()</SAMP> using the index <SAMP>datfmtIdx</SAMP>, and stores the pointer to the date format string. [For brevity, error handling is omitted in the example. If allocation fails, then <SAMP>std::ios_base::badbit</SAMP> is set.] Note that the reference returned by <SAMP>pword()</SAMP> is only used for <I>storing</I> the pointer to the date format string. Generally, you should never store a reference returned by <SAMP>iword()</SAMP> or <SAMP>pword()</SAMP> in order to access the stored data through this reference later on. This is because these references can become invalid once the array is reallocated or copied. (See the <A HREF="../stdlibref/noframes.html"><I>Standard C++ Library Module Reference Guide</I></A> for more details.)
<TR VALIGN="top"><TD><SAMP>//3</SAMP></TD><TD>The inserter for <SAMP>date</SAMP> objects needs to access the index into the array of pointers, so that it can read the format string and use it. Therefore, the inserter must be declared as a friend. In principle, the extractor must be a friend, too; however, the standard C++ locale falls short of supporting the use of format strings like the ones used by the standard C function <SAMP>strptime()</SAMP>. Hence, the implementation of a date extractor that supports date format strings would be a lot more complicated than the implementation for the inserter, which can use the stream's locale. We have omitted the extractor for the sake of brevity.
<TR VALIGN="top"><TD><SAMP>//4</SAMP></TD><TD>Initializes the index of elements in istream storage where the format string is kept.
</TABLE>
<A NAME="idx894"><!></A>
<P>The inserter for <SAMP>date</SAMP> objects given below is almost identical to the one we described in <A HREF="32-5.html#3251">Section&nbsp;32.5.1</A>:</P>

<UL><PRE>
template&lt;class charT, class Traits&gt;
std::basic_ostream&lt;charT, Traits&gt; &amp;
operator &lt;&lt; (std::basic_ostream&lt;charT, Traits &gt;&amp; os,
             const date&amp; dat)
{
 std::ios_base::iostate err = 0;
 charT* fmt  = 0;
 
 try {
  typename std::basic_ostream&lt;charT, Traits&gt;::sentry opfx(os);
 
   if(opfx)
   {
     char* patt      = static_cast&lt;char*&gt;  
                         (os.pword(setfmt.datfmtIdx);         //1
     std::size_t len = std::strlen(patt);
     fmt             = new charT[len];
 
     std::use_facet&lt;std::ctype&lt;charT&gt; &gt;(os.getloc()).
         widen(patt, patt+len, fmt);
 
     if (std::use_facet&lt;std::time_put&lt;charT,
                  std::ostreambuf_iterator&lt;charT,Traits&gt; &gt; &gt;
          (os.getloc())
          .put(os,os,os.fill(),&amp;dat.tm_date,fmt,fmt+len)      //2
          .failed()
        )
          err = std::ios_base::badbit;
     os.width(0);
   }
 }
 catch(...)
 {
   delete [] fmt;
   bool flag = false;
   try {
     os.setstate(std::ios_base::failbit);
   }
   catch(std::ios_base::failure) {
     flag = true;
   }
   if (flag)
     throw;
 }
 
 delete [] fmt;
 if ( err )
   os.setstate(err);
 return os;
}
</PRE></UL>
<P>The only change from the previous inserter is that the format string here is read from the iostream storage (in statement <SAMP>//1</SAMP>) instead of being the fixed string <SAMP>"%x"</SAMP>. The format string is then provided to the locale's time formatting facet (in statement <SAMP>//2</SAMP>).</P>

<BR>
<HR>
<A HREF="36-2.html"><IMG SRC="images/bprev.gif" WIDTH=20 HEIGHT=21 ALT="Previous file" BORDER=O></A><A HREF="noframes.html"><IMG SRC="images/btop.gif" WIDTH=56 HEIGHT=21 ALT="Top of Document" BORDER=O></A><A HREF="booktoc.html"><IMG SRC="images/btoc.gif" WIDTH=56 HEIGHT=21 ALT="Contents" BORDER=O></A><A HREF="tindex.html"><IMG SRC="images/bindex.gif" WIDTH=56 HEIGHT=21 ALT="Index page" BORDER=O></A><A HREF="36-4.html"><IMG SRC="images/bnext.gif" WIDTH=20 HEIGHT=21 ALT="Next file" BORDER=O></A></BODY>
</HTML>
